package com.yusp75.myexam.com.yusp75.myexam.data

import com.yusp75.myexam.data.Question
import com.yusp75.myexam.data.QuestionBounds
import com.yusp75.myexam.data.QuestionDao
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap

class QuestionRepository(
    private val questionDao: QuestionDao,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
    private var currentBookId: Int? = null

    private val cache = mutableMapOf<Int, List<Question>>()
    private val paperCache = ConcurrentHashMap<Int, List<Question>>()  // 取题缓存

    private val randomCache = mutableMapOf<Int, LinkedHashMap<Int, List<Question>>>()
    private val MAX_CACHE_SIZE = 100

    suspend fun getQuestionsByCursor(
        bookId: Int,
        lastId: Int,
        limit: Int,
        questionType: String?
    ): List<Question> = withContext(ioDispatcher) {
        if (bookId != currentBookId) {
            cache.clear()
            currentBookId = bookId
        }
        val query = QuestionDao.buildOrderWithTypeFilterQuery(bookId, lastId, limit, questionType)
        return@withContext questionDao.loadNextPage(query)
            .also { newPage ->
                if (newPage.isNotEmpty()) {
                    cache[newPage.last().id] = newPage
                }
            }
    }

    fun getCachedQuestions(lastId: Int): List<Question>? {
        return cache[lastId]
    }

    suspend fun getQuestionTypesCount(bookId: Int): Map<String, Int> {
        return questionDao.getQuestionTypeCounts(bookId).associate { it.questionType to it.count }
    }

    // 取题
    suspend fun getPaperQuestions(
        bookId: Int,
        numOfChoice: Int,
        numOfJudge: Int
    ): List<Question> = paperCache[bookId]?.takeIf {
        it.count { it.questionType == "choice" } >= numOfChoice &&
                it.count { it.questionType == "judge" } >= numOfJudge
    } ?: questionDao.getAdaptedQuestions(bookId, numOfChoice, numOfJudge)
        .also { cache[bookId] = it }

    // 做题结果映射
    suspend fun mapAnswersToQuestions(answers: List<ResultOfAnswer>): List<AnswerResultMap> {
        // 提取并去重所有bookId和questionId
        val bookIds = answers.map { it.bookId }.distinct()
        val questionIds = answers.map { it.questionId }.distinct()

        // 执行批量查询
        val questions = questionDao.getQuestionsByIds(
            bookIds = bookIds,
            questionIds = questionIds
        )

        // 构建内存映射表
        val questionMap = questions.associateBy { Pair(it.bookId, it.id) }

        return answers.mapNotNull { answer ->
            questionMap[Pair(answer.bookId, answer.questionId)]?.let { q ->
                AnswerResultMap(
                    idx = answer.idx,
                    userAnswer = answer.answer,
                    content = q.content,
                    correctAnswer = q.answer,
                    analysis = q.analysis
                )
            }
        }
    }

    // 更新favorite
    suspend fun updateFavoriteStatus(idx: Int, isFavorite: Boolean) {
        questionDao.updateFavoriteStatus(idx, isFavorite)
    }

    // 随机取题，类型
    suspend fun getRandomTypeQuestions(
        bookId: Int,
        limit: Int,
        random: Boolean,
        questionType: String? = null
    ): List<Question> = withContext(ioDispatcher) {
        if (bookId != currentBookId) {
            randomCache.clear()
            currentBookId = bookId
        }

        val bookCache = randomCache.getOrPut(bookId) { LinkedHashMap(16, 0.75f, true) }

        val query = QuestionDao.buildRandomTypeFilterQuery(
            bookId = bookId,
            size = limit,
            random = random,
            questionType = questionType
        )

        return@withContext questionDao.queryTypeOrderFilterByBuilder(query)
            .also { newPage ->
                if (newPage.isNotEmpty()) {
                    if (bookCache.size > MAX_CACHE_SIZE) {
                        bookCache.remove(bookCache.iterator().next().key)
                    }
                }
            }
    }

    // 分类题目的上下限
    suspend fun getQuestionBounds(type: String): QuestionBounds {
        return questionDao.getQuestionBounds(
            when (type) {
                "全部" -> null
                else -> type
            }
        )
    }


    //
}

